import React, { PureComponent } from 'react'
import { Button, Checkbox, Collapse, Row, Form, message, Tooltip } from 'antd'
import FieldMapping from 'react-field-mapping'
import { offlineTableFields, startFlowTask, stopTask, taskLog } from './api'
import { DataDevLogger } from '@/components'
import styles from './index.less'
import Tools from '@/utils/Tools'

const { Panel } = Collapse
const { Item } = Form
const Bus = Tools.Bus
const sourceCols = [
  { title: '源字段', key: 'fieldName', width: '1.6rem' },
  { title: '类型', key: 'fieldType' },
  { title: '描述', key: 'comment' },
]

export default class OfflineDetail extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      data: null,
      sourceFields: [],
      targetFields: [],
      relation: [],
      loggerList: [],
      activeKey: '0',
      runState: 0,
      resultss: [
        {
          result: '运行日志',
          value: ['暂无运行'],
          key: 'logger',
          name: '运行日志',
        },
      ],
    }
  }

  componentDidMount() {
    this.offlineDetail()
    window.onresize = () => {
      clearTimeout(this.time)
      this.time = setTimeout(() => {
        const { sourceFields, targetFields, relation } = this.state
        this.setState({
          sourceFields,
          targetFields,
          relation: [],
        }, () => {
          this.setState({
            relation,
          })
        })
      }, 500)
    }
  }

  offlineDetail = async () => {
    const { data } = this.props
    if (!data) return
    let targetFields = []; let sourceFields = []; let relation = []
    if (data.sourceDsType === 'Kafka' || data.sourceDsType === 'Mongodb' || data.sourceDsType === 'HBase') {
      sourceFields = []
      data && data.fieldMappings && data.fieldMappings.map((item) => {
        sourceFields.push({
          fieldName: item.sourceField,
          fieldType: item.sourceFieldType,
          key: item.sourceField,
        })
      })
    } else {
      sourceFields = await this.offlineTableFields(0, data.sourceDsId, data.sourceTable)
    }
    if (data.targetDsType === 'Kafka' || data.targetDsType === 'Mongodb' || data.targetDsType === 'HBase') {
      targetFields = []
      data && data.fieldMappings && data.fieldMappings.map((item) => {
        targetFields.push({
          fieldName: item.targetField,
          fieldType: item.targetFieldType,
          key: item.targetField,
        })
      })
    } else {
      targetFields = await this.offlineTableFields(1, data.targetDsId, data.targetTable)
    }

    relation = await this.setRelation(data)
    this.setState({
      data,
      sourceFields,
      targetFields,
      cycle: data && data.schedule && data.schedule.cycle,
    }, () => {
      this.setState({
        relation,
      })
    })
  }

  offlineTableFields = (direction, dsId, tables) => new Promise((resolve, reject) => {
    offlineTableFields({ direction, dsId, tables: [tables] }).then((res) => {
      if (res.status === 200) {
        const data = res.data && res.data.tables[0] && res.data.tables[0].fields
        const dataArr = []
        data && data.map((item) => {
          item.key = item.fieldName
          item.isPk = item.pk ? 1 : 0
          if (direction === 1 && !item.isPartition) {
            dataArr.push(item)
          } else if (direction === 0) {
            dataArr.push(item)
          }
        })
        resolve(dataArr)
      } else {
        resolve([])
      }
    })
  })

  setRelation = (data) => new Promise((resolve, reject) => {
    const relation = []
    data && data.fieldMappings && data.fieldMappings.map((item) => {
      relation.push({
        source: {
          fieldName: item.sourceField,
          fieldType: item.sourceFieldType,
          isPk: item.isSourceFieldPk,
          comment: item.comment,
          key: item.sourceField,
        },
        target: {
          fieldName: item.targetField,
          fieldType: item.targetFieldType,
          isPk: item.isTargetFieldPk,
          comment: item.comment,
          key: item.targetField,
        },
      })
    })
    resolve(relation)
  })

  activeKeyonChange = (activeKey) => {
    this.setState({ activeKey })
  };

  // 任务开始
  startFlowTask = () => {
    if (this.state.runState === 1) return
    const { taskNode } = this.props
    startFlowTask({
      nodeId: taskNode.id,
    }).then((res) => {
      if (res.status === 200) {
        message.success(res.msg)
        const { resultss } = this.state
        resultss[0].value = [res.msg]
        this.setState({
          jobId: res.data,
          loggerList: [res.msg],
          resultss: [...resultss],
          runState: 1,
        })
        Bus.emit('iconUpFn', this.props.taskNode.id)
        this.taskLog(res.data)
      } else {
        message.error(res.msg)
      }
    })
  }

  // 任务日志
  taskLog = (jobId, offset) => {
    taskLog({
      jobId,
      offset: offset || offset === 0 ? offset : 0,
    }).then((res) => {
      if (res.status === 200) {
        clearTimeout(this.time)
        const { logContent, logEnd, results } = res.data
        const { resultss } = this.state

        let { loggerList } = this.state
        if (logContent && logContent.length) {
          loggerList = loggerList.concat(logContent)
        }
        resultss[0].value = loggerList || []

        const arr = this.state.resultss
        let newResults = [...results]

        if (newResults && newResults.length) {
          newResults.map((obj) => {
            obj.jobId = jobId
          })
          newResults = arr.concat(newResults)
        }

        newResults && newResults.length
          ? newResults.map((item, k) => {
            item.name ? null : (item.name = `结果[${k}]`)
          })
          : null
        this.setState({
          loggerList,
          resultss: newResults && newResults.length ? newResults : arr,
        }, () => {
          this.time = setTimeout(() => {
            this.taskLog(jobId, res.data.offset)
          }, 2000)
        })
        if (logEnd) {
          clearTimeout(this.time)
          this.setState({
            runState: 0,
          })
        }
      } else {
        clearTimeout(this.time)
        this.setState({
          runState: 0,
        })
        message.error(res.msg)
      }
    })
  }

  // 结束任务
  stopTask = () => {
    if (this.state.runState === 0) return
    const { jobId } = this.state
    stopTask({ jobId }).then((res) => {
      if (res.status === 200) {
        message.success(res.msg)
        clearTimeout(this.time)
        this.setState({
          runState: 0,
        })
      } else {
        message.error(res.msg)
      }
    })
  }

  render() {
    const {
      data, sourceFields, targetFields, relation, cycle, loggerList, resultss, runState,
    } = this.state
    const { taskNode } = this.props
    return (
      <div className={`${styles.page_content} ${styles.page_content_off}`}>
        <div className={styles.back_bar}>
          <dl
            onClick={() => {
              this.startFlowTask()
            }}
            className={`${runState === 1 && styles.disable}`}
          >
            <dt><i className="iconfont icon-yunhang" /></dt>
            <dd>运行</dd>
          </dl>
          <dl
            onClick={() => {
              this.stopTask()
            }}
            className={`${runState === 0 && styles.disable}`}
          >
            <dt><i className="iconfont icon-tingzhi" /></dt>
            <dd>停止</dd>
          </dl>
          <Button onClick={() => {
            this.props.createChange()
          }}
          >编辑
          </Button>
        </div>
        <div className={styles.page_content_off_content}>
          <Form
            className={styles.form}
            colon={false}
            labelCol={{ span: 4 }}
            wrapperCol={{ span: 20 }}
          >
            <Item>
              <div className={styles.column}>数据来源</div>
            </Item>
            <Item
              label="数据来源"
            >
              <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={data && data.sourceDsName}>{data && data.sourceDsName}</div>
            </Item>
            <Item
              label="来源表"
            >
              <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={data && data.sourceTable}>{data && data.sourceTable}</div>
            </Item>
            <div>
              <Item
                label={
                  <span>
                    数据过滤
                    <Tooltip title={
                      <div>
                        <p>where 条件即针对源头数据筛选条件，根据指定的 column、table、where 条件拼接 SQL 进行数据抽取。利用 where 条件可进行全量同步和增量同步，具体说明如下：</p>
                        <p>1）全量同步：第一次做数据导入时通常为全量导入，可不用设置 where 条件。</p>
                        <p>{'2）增量同步：增量导入在实际业务场景中，往往会选择当天的数据进行同步，通常需要编写 where 条件语句，请先确认表中描述增量字段（时间戳）为哪一个。如tableA增量的字段为create_time，则填写create_time > 您需要的日期，如果需要日期动态变化，请参考帮助文档。'}</p>
                        <p>{'例如ID自增的增量同步：ID > ${to_db[select max(ID) from table_name]}'}</p>
                      </div>
                    }
                    >
                      <i className="iconfont icon-yiwentishi" />
                    </Tooltip>
                  </span>
                }
              >
                <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={data && data.incFilter}>{data && data.incFilter}</div>
              </Item>
              {/* <div
                  onClick={() => {
                    this.offlinePreviewData()
                  }}
                  className={styles.data_see}
                >数据预览
                </div> */}
            </div>
            <Item>
              <div className={styles.column}>数据目标</div>
            </Item>
            <Item
              label="数据目标"
            >
              <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={data && data.targetDsName}>{data && data.targetDsName}</div>
            </Item>
            <div className={styles.target_table}>
              <Item
                label="目标表"
              >
                <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={data && data.targetTable}>{data && data.targetTable}</div>
              </Item>
            </div>
            <Item
              label=" "
            >
              <Checkbox checked={!!(data && data.isTruncate)} disabled>同步前清空历史数据</Checkbox>
            </Item>
            <Item
              label="写入模式"
              rules={[{ required: true, message: '请选择写入模' }]}
            >
              <div
                className={`${styles.form_item} ${styles.text_overflow_single}`}
                title={
                  data && {
                    1: '覆盖（Insert Overwrite）',
                    2: '追加（Insert Into）',
                    5: '主键冲突，替换原有数据',
                    6: '主键冲突，丢弃新数据',
                  }[data.dataReplaceRuleId]
                }
              >
                {data && {
                  1: '覆盖（Insert Overwrite）',
                  2: '追加（Insert Into）',
                  5: '主键冲突，替换原有数据',
                  6: '主键冲突，丢弃新数据',
                }[data.dataReplaceRuleId]}
              </div>
            </Item>
            <Item
              className={styles.check_bar}
              label="脏数据限制"
              style={{ marginTop: '.1rem' }}
            >
              <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={`单次同步失败记录数超过${data && data.errorNumLimit}条则任务结束`}>单次同步失败记录数超过 {data && data.errorNumLimit} 条则任务结束</div>
            </Item>
            <Collapse ghost>
              <Panel header="高级配置" key="1" forceRender>
                <Item
                  label={
                    <span>
                      每次读取数据条数（fetchSize）
                      <Tooltip title={
                        <div>
                          <p>该值决定了平台每次获取数据的条数,数值越大越能够提升数据抽取性能，但应避免过大（2048）造成进程宕机。</p>
                        </div>
                      }
                      >
                        <i className="iconfont icon-yiwentishi" />
                      </Tooltip>
                    </span>
                  }
                  wrapperCol={{ span: 12, offset: 6 }}
                >
                  <div className={`${styles.form_item} ${styles.text_overflow_single}`}>{data && data.fetchSize}</div>
                </Item>
                <Item
                  label={
                    <span>
                      每次写入数据条数（batchSize）
                      <Tooltip title={
                        <div>
                          <p>该值决定了平台每次写入数据的条数，数值越大能够提升平台数据吞吐量，但应避免过大（10000）造成进程宕机。</p>
                        </div>
                      }
                      >
                        <i className="iconfont icon-yiwentishi" />
                      </Tooltip>
                    </span>
                  }
                  wrapperCol={{ span: 12, offset: 6 }}
                >
                  <div className={`${styles.form_item} ${styles.text_overflow_single}`}>{data && data.batchSize}</div>
                </Item>
                <Item
                  label={
                    <span>
                      并发数（channel）
                      <Tooltip title={
                        <div>
                          <p>该值是数据调度进程数，提高进程数可以减少数据同步时间。但应避免过大（10）造成进程宕机。</p>
                        </div>
                      }
                      >
                        <i className="iconfont icon-yiwentishi" />
                      </Tooltip>
                    </span>
                  }
                  wrapperCol={{ span: 12, offset: 6 }}
                >
                  <div className={`${styles.form_item} ${styles.text_overflow_single}`}>{data && data.channel}</div>
                </Item>
                <Item
                  label={
                    <span>
                      切片字段（splitKey）
                      <Tooltip title={
                        <div>
                          <p>该字段作为读取来源表时进行切分并行读取的依赖字段，优先选主键或唯一字段，支持字符串类型和整型；与并发数联合使用才有效。</p>
                        </div>
                      }
                      >
                        <i className="iconfont icon-yiwentishi" />
                      </Tooltip>
                    </span>
                  }
                  wrapperCol={{ span: 12, offset: 6 }}
                >
                  <div className={`${styles.form_item} ${styles.text_overflow_single}`}>{data && data.splitKey}</div>
                </Item>
              </Panel>
            </Collapse>
            <Item>
              <div className={styles.column}>字段映射</div>
            </Item>
            <div className={styles.field_mapping}>
              <FieldMapping
                {...{
                  source: {
                    data: sourceFields,
                    columns: sourceCols,
                    mutiple: false,
                  },
                  target: {
                    data: targetFields,
                    columns: sourceCols,
                    mutiple: false,
                  },
                  relation,
                  edit: false,
                  onChange: (relations) => {
                    this.setState({
                      relation: relations,
                    })
                  },
                }}
              />
            </div>
            {data && data.paritions && data.paritions.length ? <div className={styles.column}>分区字段</div> : null}
            {data && data.paritions && data.paritions.map((item) => (
              <Item
                label={item.fieldName}
              >
                <div className={`${styles.form_item} ${styles.text_overflow_single}`} title={item && item.fieldValue}>{item && item.fieldValue}</div>
              </Item>
            ))}
          </Form>
        </div>
        <DataDevLogger
          list={loggerList || []}
          jobId={this.state.jobId}
          className={styles.flow_log}
          style="flow"
          results={resultss}
          activeKey={this.state.activeKey}
          activeKeyonChange={this.activeKeyonChange}
          taskId={taskNode.id}
        />
      </div>
    )
  }
}
